<!--{
    "Title": "Return greetings for multiple people",
    "Path":  "/doc/tutorial/greetings-multiple-people"
}-->

<p>
  In the last changes you'll make to your module's code, you'll add support for
  getting greetings for multiple people in one request. In other words, you'll
  handle a multiple-value input and pair values with a multiple-value output.
</p>

<aside class="Note">
  <strong>Note:</strong> This topic is part of a multi-part tutorial that begins
  with <a href="create-module.html">Create a Go module</a>.
</aside>

<p>
  To do this, you'll need to pass a set of names to a function that can return a
  greeting for each of them. Changing the <code>Hello</code> function's
  parameter from a single name to a set of names would change the function
  signature. If you had already published the <code>greetings</code> module and
  users had already written code calling <code>Hello</code>, that change would
  break their programs. In this situation, a better choice is to give new
  functionality a new name.
</p>

<p>
  In the last code you'll add with this tutorial, update the code as if you've
  already published a version of the <code>greetings</code> module. Instead of
  changing the <code>Hello</code> function, add a new function
  <code>Hellos</code> that takes a set of names. Then, for the sake of
  simplicity, have the new function call the existing one. Keeping both
  functions in the package leaves the original for existing callers (or future
  callers who only need one greeting) and adds a new one for callers that want
  the expanded functionality.
</p>

<ol>
  <li>
    In greetings/greetings.go, change your code so it looks like the following.

    <pre>
package greetings

import (
    "errors"
    "fmt"
    "math/rand"
    "time"
)

// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
    // If no name was given, return an error with a message.
    if name == "" {
        return name, errors.New("empty name")
    }
    // Create a message using a random format.
    message := fmt.Sprintf(randomFormat(), name)
    return message, nil
}

<ins>// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
    // A map to associate names with messages.
    messages := make(map[string]string)
    // Loop through the received slice of names, calling
    // the Hello function to get a message for each name.
    for _, name := range names {
        message, err := Hello(name)
        if err != nil {
            return nil, err
        }
        // In the map, associate the retrieved message with 
        // the name.
        messages[name] = message
    }
    return messages, nil
}</ins>

// Init sets initial values for variables used in the function.
func init() {
    rand.Seed(time.Now().UnixNano())
}

// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
    // A slice of message formats.
    formats := []string{
        "Hi, %v. Welcome!",
        "Great to see you, %v!",
        "Hail, %v! Well met!",
    }

    // Return one of the message formats selected at random.
    return formats[rand.Intn(len(formats))]
}
</pre>

    <p>
      In this code, you:
    </p>

    <ul>
      <li>
        Add a <code>Hellos</code> function whose parameter is a slice of names
        rather than a single name. Also, you change one of its return types from
        a <code>string</code> to a <code>map</code> so you can return names
        mapped to greeting messages.
      </li>
      <li>
        Have the new Hellos function call the existing Hello function. This
        leaves both functions in place.
      </li>
      <li>
        Create a <code>messages</code>
        <a href="https://blog.golang.org/maps">map</a> to associate each of the
        received names (as a key) with a generated message (as a value). In Go,
        you initialize a map with the following syntax:
        <code>make(map[<em>key-type</em>]<em>value-type</em>)</code>. You have
        the <code>Hello</code> function return this map to the caller.
      </li>
      <li>
        Loop through the names your function received, checking that each has a
        non-empty value, then associate a message with each. In this
        <code>for</code> loop, <code>range</code> returns two values: the index
        of the current item in the loop and a copy of the item's value. You
        don't need the index, so you use the Go
        <a href="https://golang.org/doc/effective_go.html#blank"
          >blank identifier (an underscore)</a
        >
        to ignore it.
      </li>
    </ul>
  </li>

  <li>
    In your hello/hello.go calling code, pass a slice of names, then print the
    contents of the names/messages map you get back.

    <p>
      In hello.go, change your code so it looks like the following.
    </p>

    <pre>
package main

import (
    "fmt"
    "log"

    "example.com/greetings"
)

func main() {
    // Set properties of the predefined Logger, including
    // the log entry prefix and a flag to disable printing
    // the time, source file, and line number.
    log.SetPrefix("greetings: ")
    log.SetFlags(0)

    <ins>// A slice of names.
    names := []string{"Gladys", "Samantha", "Darrin"}</ins>

    // Request greeting messages for the names.
    messages, err := greetings.Hellos(names)
    if err != nil {
        log.Fatal(err)
    }
    // If no error was returned, print the returned map of
    // messages to the console.
    fmt.Println(messages)
}
</pre>

    <p>
      With these changes, you:
    </p>

    <ul>
      <li>
        Create a <code>names</code> variable as a slice type holding three
        names.
      </li>
      <li>
        Pass the <code>names</code> variable as the argument to the
        <code>Hellos</code> function.
      </li>
    </ul>
  </li>

  <li>
    At the command line, change to the directory that contains hello/hello.go,
    then run hello.go to confirm that the code works.

    <p>
      The output should be a string representation of the map associating names
      with messages, something like the following:
    </p>

    <pre>
$ go run hello.go
map[Darrin:Hail, Darrin! Well met! Gladys:Hi, Gladys. Welcome! Samantha:Hail, Samantha! Well met!]
</pre
    >
  </li>
</ol>

<p>
  This topic introduced maps for representing name/value pairs. It also
  introduced the idea of
  <a href="https://blog.golang.org/module-compatibility"
    >preserving backward compatibility</a
  >
  by implementing a new function for new or changed functionality in a module.
  In the tutorial's <a href="add-a-test.html">next topic</a>, you'll use
  built-in features to create a unit test for your code.
</p>

<p class="Navigation">
  <a class="Navigation-prev" href="random-greeting.html"
    >&lt; Return a random greeting</a
  >
  <a class="Navigation-next" href="add-a-test.html">Add a test &gt;</a>
</p>
